package com.yunchao.library.lock

import kotlinx.coroutines.flow.Flow

interface IDeviceHelper {

    /**
     * 打开设备
     */
    suspend fun openDevice(): Boolean

    suspend fun openEmbededDevice(): Boolean

    /**
     * 关闭设备
     */
    suspend fun closeDevice()

    /**
     * 单扫锁标签
     */
    suspend fun inventoryOnce(): LockEPCInfo

    suspend fun readLockErrorCode(): LockEPCInfo

    /**
     * 群扫锁标签
     */
    fun inventoryLoop(): Flow<List<LockEPCInfo>>

    /**
     * 关闭群扫
     */
    suspend fun inventoryStop(): Boolean

    /**
     * 设置RFID功率
     */
    suspend fun setPower(power: Int): Boolean

    /**
     * 处理锁指令
     */
    suspend fun handleLockCommand(
        lockEPCInfo: LockEPCInfo,
        action: LockAction,
        deviceId: Int,
        operatorId: Int,
        chkUserId: Int,
        pageNumber: Int,
        voucherType: String = ""
    ): LockEPCInfo


    /**
     * 读取锁信息
     */
    suspend fun readTagData(
        epcId: String,
        password: String = READ_DEFAULT_PASSWORD,
        bank: Int = 3,
        offset: Int,
        len: Int
    ): String


    /**
     * 给锁写入指令
     */
    suspend fun writeTagData(
        epcId: String,
        password: String = READ_DEFAULT_PASSWORD,
        bank: Int = 3,
        offset: Int,
        len: Int,
        data: String
    ): Boolean


    /**
     * 闭锁写物流
     */
    suspend fun closeLockWriteLogistics(
        lockEPCInfo: LockEPCInfo,
        deviceId: Int,
        operatorId: Int,
        chkUserId: Int,
        pageNumber: Int
    ): LockEPCInfo = handleLockCommand(
        lockEPCInfo,
        LockAction.CLOSE_LOCK_LOGISTICS,
        deviceId,
        operatorId,
        chkUserId,
        pageNumber
    )

    /**
     * 开锁写物流
     */
    suspend fun openLockWriteLogistics(
        lockEPCInfo: LockEPCInfo,
        deviceId: Int,
        operatorId: Int,
        chkUserId: Int,
        pageNumber: Int
    ): LockEPCInfo = handleLockCommand(
        lockEPCInfo,
        LockAction.OPEN_LOCK_LOGISTICS,
        deviceId,
        operatorId,
        chkUserId,
        pageNumber
    )

    /**
     * 闭锁
     */
    suspend fun closeLock(
        lockEPCInfo: LockEPCInfo,
        deviceId: Int,
        operatorId: Int,
        chkUserId: Int,
        pageNumber: Int
    ): LockEPCInfo = handleLockCommand(
        lockEPCInfo,
        LockAction.CLOSE_LOCK,
        deviceId,
        operatorId,
        chkUserId,
        pageNumber
    )


    /**
     * 开锁
     */
    suspend fun openLock(
        lockEPCInfo: LockEPCInfo,
        deviceId: Int,
        operatorId: Int,
        chkUserId: Int,
        pageNumber: Int
    ): LockEPCInfo = handleLockCommand(
        lockEPCInfo,
        LockAction.OPEN_LOCK,
        deviceId,
        operatorId,
        chkUserId,
        pageNumber
    )


    /**
     * 恢复锁
     */
    suspend fun recoveryLock(
        lockEPCInfo: LockEPCInfo,
        deviceId: Int,
        operatorId: Int,
        chkUserId: Int
    ): LockEPCInfo = handleLockCommand(
        lockEPCInfo,
        LockAction.RECOVERY_LOCK,
        deviceId,
        operatorId,
        chkUserId,
        lockEPCInfo.pageNumber
    )


    /**
     * 激活锁
     */
    suspend fun activateLock(
        lockEPCInfo: LockEPCInfo,
        deviceId: Int,
        operatorId: Int,
        chkUserId: Int,
        pageNumber: Int,
        voucherType: String
    ): LockEPCInfo = handleLockCommand(
        lockEPCInfo,
        LockAction.ACTIVATE_LOCK,
        deviceId,
        operatorId,
        chkUserId,
        pageNumber,
        voucherType
    )

    /**
     * 清理锁日志
     */
    suspend fun cleanLockLog(
        lockEPCInfo: LockEPCInfo,
        deviceId: Int,
        operatorId: Int,
        chkUserId: Int,
        pageNumber: Int
    ): LockEPCInfo = handleLockCommand(
        lockEPCInfo,
        LockAction.CLEAR_LOCK_LOG,
        deviceId,
        operatorId,
        chkUserId,
        pageNumber
    )

    /**
     * 锁日志总数
     */
    suspend fun readLockLogCount(lockEPCInfo: LockEPCInfo): Int

    /**
     * 读取锁物流日志
     */
    suspend fun readLockLogisticsLog(): Pair<LockEPCInfo, List<String>>

    /**
     * 读取锁日志
     */
    suspend fun readLockLog(lockEPCInfo: LockEPCInfo, start: Int, number: Int): Pair<LockEPCInfo, List<String>>


    /**
     * 通过锁id验证锁状态
     */
    suspend fun verifyLockStatus(epcId: String, password: String, action: LockAction): LockEPCInfo


    /**
     * 打开PSAM
     */
    suspend fun openPSAM(): Boolean

    suspend fun psamReset(): String?

    /**
     * 验证PSAM
     */
    suspend fun authPSAM(): Boolean

    /**
     * PSAM 发送指令返回加密后的指令
     */
    suspend fun sendApdu(cmd: String = "00", data: String): String


    companion object {

        const val READ_DEFAULT_PASSWORD: String = "00000000"
        const val PSAM_SUCCEED_INFO: String = "9000"
        const val PSAM_DEFAULT_HEX_DATA: String =
            "802000001700000000000000014D494D49535F5053414D5F55534552"

        //单扫功率
        const val SINGLE_SCAN_POWER = 10

        //群扫功率
        const val LOOP_SCAN_POWER = 30

        //读写功率
        const val READ_WRITE_POWER = 15

        const val DEFAULT_OPERATOR_1 = 100101
        const val DEFAULT_OPERATOR_2 = 100102
        const val DEFAULT_PAGE_NUMBER = 20000
        const val DEFAULT_DEVICE_ID = 1001

        const val RFID_POWER_ERROR_MESSAGE = "RFID设置功率失败"
        const val RFID_SET_INFO_ERROR_MESSAGE = "RFID设置过滤数据失败"
        const val RFID_WRITE_LOCK_CMD_MESSAGE = "RFID写入锁指令失败"
        const val RFID_READ_LOCK_INFO_MESSAGE = "RFID读取锁信息失败"
        const val RFID_INVENTORY_ONCE_LOCK_MESSAGE = "RFID单扫锁信息失败"
        const val RFID_READ_LOCK_LOG_LEN_MESSAGE = "RFID读取日志长度失败"
        const val RFID_READ_LOCK_LOG_MESSAGE = "RFID读取日志信息失败"
        const val RFID_START_LOOP_SCAN_MESSAGE = "RFID开启群扫失败"
        const val RFID_STOP_LOOP_SCAN_MESSAGE = "RFID停止群扫失败"

        const val PSAM_AUTH_ERROR_MESSAGE = "PSAM卡异常或无卡"
        const val PSAM_GET_PASSWORD_ERROR_MESSAGE = "PSAM卡生成锁密钥失败"
        const val PSAM_CREATE_CMD_ERROR_MESSAGE = "通过PSAM卡生成指令失败"
        const val PSAM_DECRYPTION_ERROR_MESSAGE = "PSAM解密出错"
    }
}